package com.concurrent.threads.foo;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @ClassName Foo
 * @Description 1114. 按序打印
 *
 * 三个不同的线程 A、B、C 将会共用一个Foo实例。
 *
 * 一个将会调用 first() 方法
 * 一个将会调用second() 方法
 * 还有一个将会调用 third() 方法
 * 请设计修改程序，以确保 second() 方法在 first() 方法之后被执行，third() 方法在 second() 方法之后被执行
 *
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/print-in-order
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 * @Author li
 * Date 2021/8/22 23:48
 * Copyright
 **/
class Foo {
    /**
     * 竞态条件：由于多进程之间的竞争执行，导致程序未按照期望的顺序输出。
     *
     * 死锁：并发程序等待一些必要资源，导致没有程序可以执行。
     *
     * 资源不足：进程被永久剥夺了运行所需的资源
     *
     * 作者：LeetCode
     * 链接：https://leetcode-cn.com/problems/print-in-order/solution/an-xu-da-yin-by-leetcode/
     * 来源：力扣（LeetCode）
     * 著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。
     */
    private final AtomicInteger atomicInteger = new AtomicInteger(1);
    public Foo() {

    }

    public void first(Runnable printFirst) throws InterruptedException {
        /**
         * 当没有达到状态时，前面线程还未执行，自旋等待
         */
        while (atomicInteger.get() != 1){

        }
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        atomicInteger.incrementAndGet();
    }

    public void second(Runnable printSecond) throws InterruptedException {
        while (atomicInteger.get()!=2){

        }
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
        atomicInteger.incrementAndGet();
    }

    public void third(Runnable printThird) throws InterruptedException {
        while (atomicInteger.get()!=3){

        }
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
        atomicInteger.incrementAndGet();
    }
}